//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

using Microsoft.Research.ScientificWorkflow;

namespace Microsoft.Research.ScientificWorkflow.TridentComposer
{
    #region Using Directives

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.ComponentModel.Design.Serialization;
    using System.Globalization;
    using System.IO;
    using System.Reflection;
    using System.Text;
    using System.Workflow.Activities;
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Serialization;
    using System.Xml;
    using Microsoft.Research.ScientificWorkflow.TridentModel;
    using Microsoft.Research.ScientificWorkflow.TridentUtilities;
    using TridentAPI;
    using Er = Microsoft.Research.DataLayer;
    using System.Linq;
    using System.Security.Cryptography;

    #endregion Using Directives

    /// <summary>
    /// This class contains the logic related to fetch all the activities from 
    /// registry and library, merging, update activities into registry etc.
    /// </summary>
    public class ActivityComposer
    {
        #region Private Member Data

        /// <summary>
        /// Registry Connection.
        /// </summary>
        Er.Connection registryConn = null;

        /// <summary>
        /// Activity meta data list.
        /// </summary>
        Collection<ActivityMetadata> activityMetadataList = new Collection<ActivityMetadata>();

        /// <summary>
        /// The list of supported activities.
        /// </summary>
        private Collection<string> supportedActivityCollection;
        bool installerInstance = false;

        /// <summary>
        /// Gets whether the activity composer is running in installer mode.
        /// </summary>
        public bool IsInstallerInstance
        {
            get
            {
                return installerInstance;
            }
        }
        #endregion

        #region Properties

        public Collection<ActivityMetadata> ActivityMetadataList
        {
            get
            {
                return this.activityMetadataList;
            }
        }

        /// <summary>
        /// The list of supported activities.
        /// </summary>
        public Collection<string> SupportedActivityCollection
        {
            get
            {
                return this.supportedActivityCollection;
            }
        }

        #endregion Properties

        #region Contructor

        /// <summary>
        /// Constructor for the Activity Composer Class. Which sets the Registry Connection.
        /// </summary>
        /// <param name="registryConnection">Registry Connection for which the Activity has to connect.</param>
        public ActivityComposer(Er.Connection registryConnection, bool installerInstance)
        {
            #region Validation
            if (null == registryConnection)
            {
                throw new ArgumentNullException("registryConnection");
            }

            #endregion

            this.installerInstance = installerInstance;
            this.registryConn = registryConnection;
            this.supportedActivityCollection = ActivityComposer.ReadSupportedComponentModelActivities();
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Read activity categories from registry.
        /// </summary>
        /// <returns></returns>
        public Collection<ActivityCategoryModel> ReadAllActivityCategories()
        {
            Collection<ActivityCategoryModel> activityCategoryModels = null;

            // Read all activity categories from the registry.
            if (null != this.registryConn && this.registryConn.Alive)
            {
                activityCategoryModels =
                    CategoriesComposer.ReadActivityCategoriesFromRegistry(this.registryConn);

                this.activityMetadataList.Clear();

                // Populate the activity metadata list from the data from the registry.
                this.PopulateActivityMetadataList();
            }

            return activityCategoryModels;
        }

        /// <summary>
        /// Populate the activity metadata list for the hidden/built-in activities.
        /// </summary>
        private void PopulateActivityMetadataList()
        {
            this.activityMetadataList.Clear();
            Collection<string> activityClasses = new Collection<string> {
                "System.Workflow.Activities.SequentialWorkflowActivity",
                "System.Workflow.Activities.SequenceActivity",
                "System.Workflow.Activities.ParallelActivity",
                "System.Workflow.Activities.ReplicatorActivity",
                "TridentBasicActivities.Activities.IfTrue",
                "TridentBasicActivities.Activities.IfFalse",
                "TridentBasicActivities.Activities.IfCondition"};

            foreach (string activityClass in activityClasses)
            {
                this.GetMetadataFromRegistry(activityClass);
            }
        }

        /// <summary>
        /// Update the Parameters of the given Activity using the Model which contains the data.
        /// 1. Update the Value for the Parameters.
        /// 2. Update the Bindings.
        /// </summary>
        /// <param name="activity">Activity for which the parameters has to be updated.</param>
        /// <param name="actModel">Activity Model which contains the updated Parameters.</param>
        public void UpdateParameter(
            Activity activity,
            BaseModel actModel,
            bool nullifyForCustomTypes)
        {
            #region Validation of Arguments
            if (null == activity)
            {
                throw new ArgumentNullException("activity");
            }

            if (null == actModel)
            {
                throw new ArgumentNullException("actModel");
            }
            #endregion

            this.UpdateParameter(actModel, activity, nullifyForCustomTypes);
        }

        /// <summary>
        /// This is used to get the Activity Meta of the ActivityName.
        ///     The activty meta is retrieved from the list which 
        ///     contains all the ActivityMeta loaded in the left pane.
        /// </summary>
        /// <param name="activityName">Activity Name.</param>
        /// <returns>ActivityMeta for the activity name.</returns>
        public ActivityMetadata GetMetadata(string activityName)
        {
            #region Validation of Arguments

            if (string.IsNullOrEmpty(activityName))
            {
                throw new ArgumentNullException("activityName");
            }

            #endregion

            ActivityMetadata result = null;
            if (this.activityMetadataList != null)
            {
                foreach (ActivityMetadata metadata in this.activityMetadataList)
                {
                    if (metadata.ActivityClass.Equals(activityName))
                    {
                        result = metadata;
                        break;
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// This is used to get the activity model of the specifies type.
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public CompositeActivityModel GetActivityModel(string type)
        {
            if (string.IsNullOrEmpty(type))
            {
                throw new ArgumentNullException("type");
            }

            ModelFactory modelFactory = new ModelFactory(this.activityMetadataList, this.supportedActivityCollection);
            CompositeActivityModel result = null;
            ActivityMetadata metadata = this.GetMetadata(type);
            if (metadata != null)
            {
                // 0 is set because it is the first activity.
                result = modelFactory.FetchModelByActivityMetadata(metadata, "0", null) as CompositeActivityModel;
            }
            else
            {
                if (0 == string.Compare(type, "System.Workflow.Activities.SequentialWorkflowActivity", true, CultureInfo.CurrentUICulture))
                {
                    result = modelFactory.FetchModelByActivity(new SequentialWorkflowActivity("SequentialActivty0"), null) as CompositeActivityModel;
                }
            }

            return result;
        }
        /// <summary>
        /// Creates the AssemblyImage Package in the Registry for the activities.
        /// This package conatains all the images that the activity references.
        /// </summary>
        /// <param name="references">
        /// Collection of FileReference objects.
        /// </param>
        /// <param name="containsActivity">
        /// True if references contains an activity, False otherwise.
        /// </param>
        /// <returns>
        /// Collection of AssemblyPackages.
        /// </returns>
        public Collection<Er.AssemblyPackage> GetAssemblyPackage(Collection<FileReference> references, bool containsActivity)
        {
            Collection<FileReference> activityList = new Collection<FileReference>();
            if (containsActivity)
            {
                activityList = ActivityComposer.BuildActivityReferences(references);
            }
            else
            {
                activityList = ActivityComposer.BuildTypeInitializerReferences(references);
            }

            Collection<Er.AssemblyPackage> asmPackages = new Collection<Er.AssemblyPackage>();
            foreach (FileReference fileRef in activityList)
            {
                Er.AssemblyImage asmImg = null;
                Er.AssemblyPackage asmPkg = null;
                Assembly currentAssembly = AssemblyLoad.LoadFrom(fileRef.FilePath);

                // Get the Assembly package from registry.
                string latestNamespace = Path.GetFileNameWithoutExtension(fileRef.FilePath);
                asmPkg = this.GetAssemblyPackage(latestNamespace);

                if (containsActivity)
                {
                    // Get the Assembly imgae related to the Assembly.
                    asmImg = this.GetAssemblyImage(currentAssembly);
                }
                else
                {
                    asmImg = this.CreateAssemblyImage(currentAssembly);
                }

                if (asmImg != null && !ActivityComposer.IsAssemblyImageAvailable(asmPkg.AssemblyImages, asmImg))
                {
                    // Add the reference of the Assembly Image to the Assembly package.
                    asmPkg.AssemblyImages.Add(asmImg);
                }

                foreach (string path in fileRef.References)
                {
                    if (Helper.IsAssemblyFile(path))
                    {
                        if (Helper.IsManagedAssembly(path))
                        {
                            // Get the Assembly imgae related to the Assembly.
                            Assembly refAssembly = AssemblyLoad.LoadFrom(path);
                            if (containsActivity)
                            {
                                asmImg = this.GetAssemblyImage(refAssembly);
                            }
                            else
                            {
                                asmImg = this.CreateAssemblyImage(refAssembly);
                            }
                        }
                        else
                        {
                            if (containsActivity)
                            {
                                asmImg = this.GetAssemblyImage(path);
                            }
                            else
                            {
                                asmImg = this.CreateAssemblyImage(path);
                            }
                        }
                    }
                    else if (!Helper.IsWorkflowFile(path))
                    {
                        asmImg = this.GetAssemblyImage(path);
                    }

                    if (asmImg != null && !ActivityComposer.IsAssemblyImageAvailable(asmPkg.AssemblyImages, asmImg))
                    {
                        // Add the reference of the Assembly Image to the Assembly package.
                        asmPkg.AssemblyImages.Add(asmImg);
                    }
                }

                asmPkg.Refresh();
                asmPackages.Add(asmPkg);
            }

            return asmPackages;
        }

        /// <summary>
        /// Save the assembly in the Registry and return the AssemblyImage object.
        /// </summary>
        /// <param name="actAssembly">Assembly which has to be stored in the registry.</param>
        /// <returns>AssemblyImage Instance.</returns>
        public Er.AssemblyImage GetAssemblyImage(Assembly actAssembly)
        {
            Er.AssemblyImage asmImg = null;
            FileInfo file = new FileInfo(actAssembly.Location);
            if (Er.AssemblyImage.Exists(file.Name, this.registryConn))
            {
                asmImg = Er.AssemblyImage.Load(file.Name, this.registryConn);
            }
            else
            {
                if (null != file)
                {
                    asmImg = this.CreateAssemblyImage(file.Name, file);
                }
            }

            return asmImg;
        }

        /// <summary>
        /// Save the assembly in the Registry and return the AssemblyImage object.
        /// </summary>
        /// <param name="actAssembly">Assembly which has to be stored in the registry.</param>
        /// <returns>AssemblyImage Instance.</returns>
        public Er.AssemblyImage CreateAssemblyImage(Assembly actAssembly)
        {
            Er.AssemblyImage asmImg = null;
            FileInfo file = new FileInfo(actAssembly.Location);
            if (null != file)
            {
                asmImg = this.CreateAssemblyImage(file.Name, file);
            }

            return asmImg;
        }

        /// <summary>
        /// Returns an assembly image for the specified file.
        /// </summary>
        /// <param name="filePath">
        /// Location of the file.
        /// </param>
        /// <returns>
        /// AssemblyImage Instance.
        /// </returns>
        public Er.AssemblyImage GetAssemblyImage(string filePath)
        {
            Er.AssemblyImage asmImg = null;
            if (Er.AssemblyImage.Exists(filePath, this.registryConn))
            {
                asmImg = Er.AssemblyImage.Load(filePath, this.registryConn);
            }
            else
            {
                FileInfo fileInfo = new FileInfo(filePath);
                asmImg = this.CreateAssemblyImage(filePath, fileInfo);
            }

            return asmImg;
        }

        /// <summary>
        /// Returns an assembly image for the specified file.
        /// </summary>
        /// <param name="filePath">
        /// Location of the file.
        /// </param>
        /// <returns>
        /// AssemblyImage Instance.
        /// </returns>
        public Er.AssemblyImage CreateAssemblyImage(string filePath)
        {
            Er.AssemblyImage asmImg = null;
            FileInfo fileInfo = new FileInfo(filePath);

            asmImg = this.CreateAssemblyImage(filePath, fileInfo);

            return asmImg;
        }

        /// <summary>
        /// Get version detail from Assembly Full Name Information.
        /// </summary>
        /// <param name="fullName">Name from which the version has to be extracted.</param>
        /// <returns>Version of the Assembly.</returns>
        public static string GetName(string fullName)
        {
            string name = string.Empty;
            string[] words = fullName.Split(',');
            if (null != words && words.Length > 0)
            {
                name = words[0];
            }

            return name;
        }

        /// <summary>
        /// This is used to Create activity in the registry.
        /// </summary>
        /// <param name="actType">Type of the Activity.</param>
        /// <returns>Activity Created in Registry.</returns>
        public Er.Activity CreateActivity(Type actType, Collection<FileReference> references, Er.Namespace actCategory, Er.AssemblyPackage package)
        {
            #region Validation of Arguments

            if (null == actType)
            {
                throw new ArgumentNullException("actType");
            }

            #endregion

            // Create activity in registry.
            Er.Activity regActivity = GetActivity(actType);

            // Update the activity details.
            ImportActivity.UpdateActivityDetails(regActivity, actType);

            // Update the category.
            ImportActivity.UpdateActivityCategory(regActivity, actType, actCategory, this.registryConn, this.installerInstance);

            // Create activity parameters.
            ImportActivity.CreateActivityParameters(regActivity, actType, this.registryConn);

            if (package == null)
            {
                // Create assembly package.
                this.CreateAssemblyPackage(regActivity, actType, references, true);
            }
            else
            {
                // Add the package
                regActivity.AssemblyPackages.Add(package);
            }

            regActivity.Refresh();

            return regActivity;
        }

        /// <summary>
        /// Creates the ComponentModel.Activity from the CompositeActivityModel.
        /// </summary>
        /// <param name="actModel">Activity Model for which the ComponentModel.Activty has to be created.</param>
        /// <param name="loadedAssemblyList">Assemblies which has been loaded.</param>
        /// <returns>ComponentModel.Activty created.</returns>
        public Activity CreateCompModelActivity(
            CompositeActivityModel compositeActivityModel,
            Collection<Assembly> loadedAssemblyList)
        {
            #region Validation of Arguments
            if (null == compositeActivityModel)
            {
                throw new ArgumentNullException("compositeActivityModel");
            }
            #endregion

            Activity wfAct = null;
            Type wfActType = null;

            // Search the type in all the assemblies which have been loaded.
            foreach (Assembly asm in loadedAssemblyList)
            {
                wfActType = asm.GetType(compositeActivityModel.ActivityClass, false);
                if (null != wfActType)
                {
                    break;
                }
            }

            // Create an activity instance of the required type.
            if (null != wfActType)
            {
                if (wfActType.IsSubclassOf(typeof(Activity)))
                {
                    wfAct = ActivityComposer.CreateActivityInstance(wfActType);
                    if (null != wfAct)
                    {
                        wfAct.Name = compositeActivityModel.UniqueId;
                        wfAct.Description = compositeActivityModel.Description;

                        // Check if the activity created is a composite activity. If so recurse through its children.
                        CompositeActivity wfCompAct = wfAct as CompositeActivity;
                        if (null != wfCompAct)
                        {
                            int insertAt = 0;

                            // Iterate through the children.
                            for (int index = 0; index < compositeActivityModel.Children.Count; index++)
                            {
                                Activity childActivity = null;

                                // Depending on the type of activity model call the required overload.
                                BaseModel childActModel = compositeActivityModel.Children[index];
                                if (childActModel.IsSimpleActivityModel)
                                {
                                    childActivity = ActivityComposer.CreateCompModelActivity(childActModel as SimpleActivityModel, loadedAssemblyList);

                                    // Add the created activity to the parent.
                                    if (null != childActivity)
                                    {
                                        wfCompAct.Activities.Insert(insertAt++, childActivity);
                                    }
                                }
                                else if (childActModel.IsCompositeActivityModel)
                                {
                                    childActivity = this.CreateCompModelActivity(childActModel as CompositeActivityModel, loadedAssemblyList);

                                    // Add the created activity to the parent.
                                    if (null != childActivity)
                                    {
                                        wfCompAct.Activities.Insert(insertAt++, childActivity);
                                    }
                                }
                                else if (childActModel.IsSubsectionModel)
                                {
                                    TridentSubsectionModel subsectionModel = childActModel as TridentSubsectionModel;
                                    insertAt = this.CreateActivitiesFromSubsection(wfCompAct, subsectionModel, loadedAssemblyList, insertAt);
                                }
                            }
                        }
                    }
                }
            }

            return wfAct;
        }

        /// <summary>
        /// Creates the ComponentModel.Activity from the CompositeActivityModel. Used when processing blackbox workflows.
        /// </summary>
        /// <param name="actModel">Activity Model for which the ComponentModel.Activty has to be created.</param>
        /// <param name="referenceActivity">The activity to be used as reference when processing blackbox workflows.</param>
        /// <param name="loadedAssemblyList">Assemblies which has been loaded.</param>
        /// <returns>ComponentModel.Activty created.</returns>
        public Activity CreateCompModelActivity(
            CompositeActivityModel actModel,
            Activity referenceActivity,
            ServiceContainer serializerService,
            Collection<Assembly> loadedAssemblyList)
        {
            #region Validation of Arguments
            if (null == actModel)
            {
                throw new ArgumentNullException("actModel");
            }
            #endregion

            Activity wfAct = null;
            Type wfActType = null;

            // Search the type in all the assemblies which have been loaded.
            foreach (Assembly asm in loadedAssemblyList)
            {
                wfActType = asm.GetType(actModel.ActivityClass, false);
                if (null != wfActType)
                {
                    break;
                }
            }

            // Create an activity instance of the required type.
            if (null != wfActType)
            {
                if (wfActType.IsSubclassOf(typeof(Activity)))
                {
                    wfAct = ActivityComposer.CreateActivityInstance(wfActType);

                    if (null != wfAct)
                    {
                        wfAct.Name = actModel.UniqueId;
                        wfAct.Description = actModel.Description;

                        // Check if the activity created is a composite activity. If so recurse through its children.
                        CompositeActivity wfCompAct = wfAct as CompositeActivity;
                        if (null != wfCompAct)
                        {
                            // Update the child models.
                            this.UpdateCompositeActivity(actModel, wfCompAct, referenceActivity, serializerService, loadedAssemblyList);
                        }
                    }
                }
            }

            return wfAct;
        }

        /// <summary>
        /// Gets the dependency property for the given Type.
        /// </summary>
        /// <param name="actType">Type from the dependency propety has to be extracted.</param>
        /// <param name="name">Name of the Dependency propery.</param>
        /// <returns>Dependency property if present.</returns>
        public static DependencyProperty GetDependencyProperty(
            System.Type type,
            string name)
        {
            FieldInfo field = type.GetField(name);
            while (field == null && type.BaseType != null)
            {
                type = type.BaseType;
                field = type.GetField(name);
            }
            if (field != null)
                return field.GetValue(type) as DependencyProperty;
            return null;
        }


        /// <summary>
        /// Import the custom types from the passed assembly.
        /// </summary>
        /// <param name="assemblyPath">The path of the assembly.</param>
        public OperationStatus ImportCustomTypeInitializers(string assemblyPath)
        {
            if (string.IsNullOrEmpty(assemblyPath))
            {
                throw new ArgumentNullException("assemblyPath");
            }

            if (File.Exists(assemblyPath))
            {
                try
                {
                    Collection<FileReference> references = new Collection<FileReference>();
                    Helper.BuildReferences(references, assemblyPath, Path.GetDirectoryName(assemblyPath));

                    this.CheckIfReferencesPresentRegistry(references);

                    if (!ActivityComposer.CanContinueWithImport(references, assemblyPath))
                    {
                        return OperationStatus.NoActionRequired;
                    }

                    Assembly depAsm = AssemblyLoad.LoadFrom(assemblyPath);
                    Er.AssemblyPackage asmPkg = null;

                    // Get a list of the types in the assembly which are already present in registry.
                    // Storing this list saves another ping to registry to retrieve values.
                    List<Er.TypeInitializer> registryCustomTypeInitializers = this.GetExistingCustomTypeInitializersList(depAsm);

                    // Build a list of types in the registry to show to the user.
                    StringBuilder customTypesInitializerIssueList = new StringBuilder();
                    foreach (Er.TypeInitializer customTypeInitializer in registryCustomTypeInitializers)
                    {
                        customTypesInitializerIssueList.Append(customTypeInitializer.Name);
                        customTypesInitializerIssueList.Append(", ");
                    }

                    // Get a confirmation from the user if he wants to replace the types in the registry.
                    // If yes then continue else do not add any of the types.
                    if (!string.IsNullOrEmpty(customTypesInitializerIssueList.ToString()))
                    {
                        string userMessage = TridentResourceManager.GetString("CustomTypeInitializerOverwrite", customTypesInitializerIssueList.ToString().Substring(0, customTypesInitializerIssueList.Length - 2));

                        if (System.Windows.MessageBox.Show(
                            userMessage,
                            "Scientific WorkFlow",
                            System.Windows.MessageBoxButton.YesNo,
                            System.Windows.MessageBoxImage.Question,
                            System.Windows.MessageBoxResult.Yes) == System.Windows.MessageBoxResult.No)
                        {
                            return OperationStatus.UserCancel;
                        }
                    }

                    // Iterate through the assembly for types for the first type 
                    // of custom type and then update the packages and store that assembly Package.
                    foreach (System.Type customTypeInitializer in depAsm.GetTypes())
                    {
                        // Search only the BaseTypeInitializer types.
                        if (customTypeInitializer.IsSubclassOf(typeof(BaseTypeInitializer)))
                        {
                            // update the Packages
                            if (!customTypeInitializer.Assembly.GlobalAssemblyCache)
                            {
                                asmPkg = this.UpdateAssemblyPackage(customTypeInitializer, references, false);
                            }

                            break;
                        }
                    }

                    if (null == asmPkg)
                    {
                        return OperationStatus.Fail;
                    }

                    // Iterate through the assembly for types.
                    foreach (System.Type customTypeInitializer in depAsm.GetTypes())
                    {
                        // Search only the BaseTypeInitializer types.
                        if (customTypeInitializer.IsSubclassOf(typeof(BaseTypeInitializer)))
                        {
                            Er.TypeInitializer regType = ActivityComposer.FetchCustomTypeInitializerIfAvailable(registryCustomTypeInitializers, customTypeInitializer.FullName);

                            // If type is in registry then update else create new,
                            if (regType != null)
                            {
                                this.UpdateCustomTypeInitializer(regType, customTypeInitializer);
                            }
                            else
                            {
                                regType = this.CreateCustomTypeInitializer(customTypeInitializer);
                            }

                            // Clear existing packages, and add the current package.
                            if (ActivityComposer.FetchAssemblyPackageIfAvailableCustomType(regType.AssemblyPackages, asmPkg))
                            {
                                regType.AssemblyPackages.Clear();
                            }

                            if (regType != null)
                            {
                                regType.Save();
                                regType.AssemblyPackages.Add(asmPkg);
                            }
                            else
                            {
                                return OperationStatus.Fail;
                            }
                        }
                    }

                    return OperationStatus.Success;
                }
                catch (BadImageFormatException ex)
                {
                    TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000024, ex.Message);
                }
                catch (FileLoadException ex)
                {
                    TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000024, ex.Message);
                }
                catch (TargetInvocationException)
                {
                    TridentErrorHandler.ThrowTridentCustomException(
                        TridentErrorConstants.ErrorNumber4000026,
                        TridentResourceManager.GetString("ImportOfCustomTypeInitializerFailed"));
                }
            }
            else
            {
                TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000025,
                    TridentResourceManager.GetString("FileNotFound", assemblyPath));
            }

            return OperationStatus.Fail;
        }
        #endregion

        #region Internal Methods
        /// <summary>
        /// Download the required dlls for the activity.
        /// </summary>
        /// <param name="rootActModel">The activity.</param>
        /// <param name="dllDirectoryPath">Path to be downloaded to.</param>
        internal void DownloadLibraries(BaseModel rootModel, string dllDirectoryPath)
        {
            if (rootModel.IsSimpleActivityModel || rootModel.IsCompositeActivityModel)
            {
                if (!rootModel.Id.Equals(Guid.Empty))
                {
                    Er.Activity rootAct = null;
                    try
                    {
                        rootAct = Er.Activity.Load(rootModel.Id, this.registryConn);
                        ActivityComposer.DownloadLibraries(rootAct, dllDirectoryPath);
                        ActivityComposer.DownloadCustomInitializerLibraries(rootModel, dllDirectoryPath);
                    }
                    catch (Microsoft.Research.DataLayer.RecordNotFoundException)
                    {
                        throw new TridentCustomException(string.Format(CultureInfo.InvariantCulture, TridentResourceManager.GetString("ActivityNotFound"), rootModel.Name));

                    }
                    catch (Exception exp)
                    {
                        TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(exp);
                        TridentErrorHandler.HandleAndThrowBusinessLogicException(
                             exp,
                             TridentErrorConstants.ErrorNumber6000018,
                             exp.Message);
                    }
                }
            }

            BaseCompositeModel compositeModel = rootModel as BaseCompositeModel;
            if (compositeModel != null)
            {
                foreach (BaseModel actModel in compositeModel.Children)
                {
                    this.DownloadLibraries(actModel, dllDirectoryPath);
                }
            }
        }

        /// <summary>
        /// Download the binaries of the workflow.
        /// </summary>
        /// <param name="workflowActivity">The workflow activity</param>
        /// <param name="dllPath">The path the libraries are to be downloaded.</param>
        internal static void DownloadWorkflowLibraries(Er.ActivitySequence workflowActivity, string dllPath)
        {
            if (workflowActivity == null)
            {
                throw new ArgumentNullException("workflowActivity");
            }

            DownloadLibraries(workflowActivity.Activity, dllPath);

            if (workflowActivity.Activity.IsComposite)
            {
                foreach (Er.ActivitySequence actsSeq in workflowActivity.Children)
                {
                    DownloadWorkflowLibraries(actsSeq, dllPath);
                }
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Check if the file references exist in registry.
        /// </summary>
        /// <param name="fileReferences">The file references.</param>
        private void CheckIfReferencesPresentRegistry(Collection<FileReference> fileReferences)
        {
            foreach (FileReference file in fileReferences)
            {
                if (!file.CopyExistsInRegistry.HasValue)
                {
                    if (!Helper.IsWorkflowFile(file.FilePath))
                    {
                        // If the image is already in the registry store the Image ID so that it will be easier to retrieve the image.
                        Helper.GetImageFromRegistry(file, this.registryConn);
                    }
                    else
                    {
                        file.CopyExistsInRegistry = false;
                    }
                }
            }
        }

        /// <summary>
        /// Check if activities need import.
        /// </summary>
        /// <returns>True if any new files exist; False otherwise.</returns>
        private static bool CanContinueWithImport(Collection<FileReference> fileReferences, string assemblyPath)
        {
            try
            {
                FileReference typeInitReference = fileReferences.FirstOrDefault(f => f.FilePath.Equals(assemblyPath, StringComparison.OrdinalIgnoreCase));
                Collection<FileReference> associatedFiles = new Collection<FileReference>();
                FileReference.GetAllAssociatedFiles(typeInitReference, fileReferences, associatedFiles);

                return ActivityComposer.CheckIfImportRequired(typeInitReference, associatedFiles);
            }
            catch
            {
                // Do nothing.
            }
            return false;
        } 

        /// <summary>
        /// Check if an import is needed for the Dlls selected. 
        /// If a package exists with all the files the user has selected then an import is not necessary.
        /// </summary>
        /// <param name="assemblyFile">The activity file.</param>
        /// <param name="fileAssociations">The file associations of the activity.</param>
        /// <returns>True if an import is necessary. False otherwise.</returns>
        public static bool CheckIfImportRequired(FileReference assemblyFile, Collection<FileReference> fileAssociations)
        {
            bool importRequired = false;

            // First level of check- If the activity dll itself is not present in registry then import is necessary.
            if (!assemblyFile.CopyExistsInRegistry.HasValue || !assemblyFile.CopyExistsInRegistry.Value)
            {
                importRequired = true;
            }
            else if (fileAssociations.Any(a => (!a.CopyExistsInRegistry.Value)))
            {
                // Second level of check. If any file is new then import required.
                importRequired = true;
            }

            return importRequired;
        }

        /// <summary>
        /// Fetch activity metadata for the hidden activities. Used by the model factory to build the ActivityModel.
        /// </summary>
        /// <param name="activityClass">The activity class.</param>
        /// <returns>The required metadata.</returns>
        private void GetMetadataFromRegistry(string activityClass)
        {
            Collection<Er.Activity> activities = Er.Activity.CommonSearches.GetActivitiesByName(activityClass, this.registryConn);
            if (activities != null)
            {
                foreach (Er.Activity activity in activities)
                {
                    this.activityMetadataList.Add(new ActivityMetadata(activity));
                }
            }
        }

        /// <summary>
        /// Creates the ComponentModel.Activity from the Blackbox model. Used when processing blackbox workflows.
        /// </summary>
        /// <param name="actModel">Activity Model for which the ComponentModel.Activty has to be created.</param>
        /// <param name="referenceActivity">The activity to be used as reference when processing blackbox workflows.</param>
        /// <param name="loadedAssemblyList">Assemblies which has been loaded.</param>
        /// <returns>ComponentModel.Activty created.</returns>
        private Activity CreateCompModelActivity(
            CompositeBlackboxModel actModel,
            Activity referenceActivity,
            ServiceContainer serializationService,
            Collection<Assembly> loadedAssemblyList)
        {
            #region Validation of Arguments
            if (null == actModel)
            {
                throw new ArgumentNullException("actModel");
            }
            #endregion

            Activity clonedActivity = null;
            Activity wfAct = referenceActivity.GetActivityByName(actModel.UniqueId);

            if (null != wfAct)
            {
                clonedActivity = ActivityComposer.CreateClone(wfAct, serializationService);

                // Check if the activity created is a composite activity. If so clear the children and recurse through the model.
                CompositeActivity wfCompAct = clonedActivity as CompositeActivity;

                if (null != wfCompAct)
                {
                    wfCompAct.Activities.Clear();

                    // Update the child models.
                    this.UpdateCompositeActivity(actModel, wfCompAct, referenceActivity, serializationService, loadedAssemblyList);
                }
            }

            return clonedActivity;
        }

        /// <summary>
        /// Create activities present within a subsection.
        /// </summary>
        /// <param name="parent">Parent activity.</param>
        /// <param name="subsection">The subsection model.</param>
        /// <param name="loadedAssemblyList">List of loaded assemblies.</param>
        private int CreateActivitiesFromSubsection(
            CompositeActivity parent,
            TridentSubsectionModel subsection,
            Collection<Assembly> loadedAssemblyList,
            int insertIndex)
        {
            // Get the start index of the subsection. The instertion of child elements starts at this point.            
            int insertAt = insertIndex;

            // Depending on the type of the child activity call the dependent overload.
            for (int index = 0; index < subsection.Children.Count; index++)
            {
                BaseModel childActModel = subsection.Children[index];
                Activity childActivity = null;
                if (childActModel.IsSimpleActivityModel)
                {
                    SimpleActivityModel simpleActivityModel = childActModel as SimpleActivityModel;
                    childActivity = ActivityComposer.CreateCompModelActivity(simpleActivityModel, loadedAssemblyList);
                    parent.Activities.Insert(insertAt++, childActivity);
                }
                else if (childActModel.IsCompositeActivityModel)
                {
                    CompositeActivityModel compositeActivityModel = childActModel as CompositeActivityModel;
                    childActivity = this.CreateCompModelActivity(compositeActivityModel, loadedAssemblyList);
                    parent.Activities.Insert(insertAt++, childActivity);
                }
                else if (childActModel.IsSubsectionModel)
                {
                    TridentSubsectionModel subsectionModel = childActModel as TridentSubsectionModel;
                    insertAt = this.CreateActivitiesFromSubsection(parent, subsectionModel, loadedAssemblyList, insertAt);
                }
            }

            return insertAt;
        }

        /// <summary>
        /// Create activities present within a subsection.
        /// </summary>
        /// <param name="parent">Parent activity.</param>
        /// <param name="subsection">The subsection model.</param>
        /// <param name="loadedAssemblyList">List of loaded assemblies.</param>
        private int CreateActivitiesFromSubsection(CompositeActivity parent,
            TridentSubsectionModel subsection,
            Activity referenceActivity,
            ServiceContainer serializationService,
            Collection<Assembly> loadedAssemblyList,
            int insertIndex)
        {
            // Get the start index of the subsection. The instertion of child elements starts at this point.            
            int insertAt = insertIndex;

            // Depending on the type of the child activity call the dependent overload.
            for (int index = 0; index < subsection.Children.Count; index++)
            {
                BaseModel childActModel = subsection.Children[index];
                Activity childActivity = null;
                if (childActModel.IsSimpleActivityModel)
                {
                    SimpleActivityModel simpleActivityModel = childActModel as SimpleActivityModel;
                    childActivity = ActivityComposer.CreateCompModelActivity(simpleActivityModel, loadedAssemblyList);
                    parent.Activities.Insert(insertAt++, childActivity);
                }
                else if (childActModel.IsCompositeActivityModel)
                {
                    CompositeActivityModel compositeActivityModel = childActModel as CompositeActivityModel;
                    childActivity = this.CreateCompModelActivity(compositeActivityModel, loadedAssemblyList);
                    parent.Activities.Insert(insertAt++, childActivity);
                }
                else if (childActModel.IsSubsectionModel)
                {
                    TridentSubsectionModel subsectionModel = childActModel as TridentSubsectionModel;
                    this.CreateActivitiesFromSubsection(parent, subsectionModel, referenceActivity, serializationService, loadedAssemblyList, insertAt);
                }
                else if (childActModel.IsSimpleBlackBoxModel)
                {
                    SimpleBlackboxModel simpleBlackbox = childActModel as SimpleBlackboxModel;
                    childActivity = ActivityComposer.CreateCompModelActivity(simpleBlackbox, referenceActivity, serializationService);
                    parent.Activities.Insert(insertAt++, childActivity);
                }
                else if (childActModel.IsCompositeBlackBoxModel)
                {
                    CompositeBlackboxModel compositeBlackbox = childActModel as CompositeBlackboxModel;
                    childActivity = this.CreateCompModelActivity(compositeBlackbox, referenceActivity, serializationService, loadedAssemblyList);
                    parent.Activities.Insert(insertAt++, childActivity);
                }
            }
            return insertAt;
        }

        /// <summary>
        /// Gets the Short Name of the property.
        /// </summary>
        /// <param name="name">name which contains the Full Name of the property.</param>
        /// <returns>Short name.</returns>
        private static string ShortName(string name)
        {
            int pos = name.LastIndexOf('.');
            if (pos > 0)
            {
                return name.Substring(pos + 1);
            }
            return name;
        }


        /// <summary>
        /// This function is used to create the activity in registry if not present.
        /// </summary>
        /// <param name="actType">Type of the Activity.</param>
        /// <returns></returns>
        private Er.Activity GetActivity(
            System.Type actType)
        {
            Er.Activity regActivity = null;
            string activityName = actType.Name;

            // Get the activity type.
            Er.ActivityType activityType = Er.ActivityType.Leaf;
            if (actType.IsSubclassOf(typeof(CompositeActivity)) ||
                actType.IsInstanceOfType(typeof(CompositeActivity)))
            {
                activityType = Er.ActivityType.Composite;
            }

            try
            {
                // Create Activity in registry.
                regActivity = Er.Activity.Create(activityName, activityType, TridentAuthentication.LoggedInUser, this.registryConn);

                // Save the registry activity.
                regActivity.Save();

            }
            catch (Exception exp)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(exp);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(
                          exp,
                          TridentErrorConstants.ErrorNumber6000014,
                          TridentResourceManager.GetString("ActivityCreateError"));
            }

            return regActivity;
        }

        /// <summary>
        /// Update the composite activity model.
        /// </summary>
        /// <param name="actModel">Base composite model.</param>
        /// <param name="wfCompAct">Component model activity</param>
        /// <param name="referenceActivity">Component model activity.</param>
        /// <param name="serializationService">Serialization Service.</param>
        /// <param name="loadedAssemblyList">Loaded assembly list.</param>
        private void UpdateCompositeActivity(
            BaseCompositeModel actModel,
            CompositeActivity wfCompAct,
            Activity referenceActivity,
            ServiceContainer serializationService,
            Collection<Assembly> loadedAssemblyList)
        {
            int insertAt = 0;

            // Iterate through the children.
            for (int index = 0; index < actModel.Children.Count; index++)
            {
                Activity childActivity = null;

                // Depending on the type of activity model call the required overload.
                BaseModel childActModel = actModel.Children[index];

                if (childActModel.IsSimpleActivityModel)
                {
                    SimpleActivityModel simpleActivityModel = childActModel as SimpleActivityModel;
                    childActivity = ActivityComposer.CreateCompModelActivity(simpleActivityModel, loadedAssemblyList);
                }
                else if (childActModel.IsCompositeActivityModel)
                {
                    CompositeActivityModel compositeActivityModel = childActModel as CompositeActivityModel;
                    childActivity = this.CreateCompModelActivity(compositeActivityModel, referenceActivity, serializationService, loadedAssemblyList);
                }
                else if (childActModel.IsSubsectionModel)
                {
                    TridentSubsectionModel subsectionModel = childActModel as TridentSubsectionModel;
                    insertAt = this.CreateActivitiesFromSubsection(wfCompAct, subsectionModel, referenceActivity, serializationService, loadedAssemblyList, insertAt);
                }
                else if (childActModel.IsSimpleBlackBoxModel)
                {
                    SimpleBlackboxModel simpleBlackbox = childActModel as SimpleBlackboxModel;
                    childActivity = ActivityComposer.CreateCompModelActivity(simpleBlackbox, referenceActivity, serializationService);
                }
                else if (childActModel.IsCompositeBlackBoxModel)
                {
                    CompositeBlackboxModel compositeBlackbox = childActModel as CompositeBlackboxModel;
                    childActivity = this.CreateCompModelActivity(compositeBlackbox, referenceActivity, serializationService, loadedAssemblyList);
                }

                // Add the created activity to the parent.
                if (null != childActivity)
                {
                    wfCompAct.Activities.Insert(insertAt++, childActivity);
                }
            }
        }

        /// <summary>
        /// Get version detail from Assembly Full Name Information.
        /// </summary>
        /// <param name="fullName">Name from which the version has to be extracted.</param>
        /// <returns>Version of the Assembly.</returns>
        public static string GetVersion(string fullName)
        {
            string version = string.Empty;

            string[] words = fullName.Split(',');

            foreach (string word in words)
            {

                if (word.Contains("Version="))
                {
                    version = word.Substring(word.IndexOf("Version=", StringComparison.Ordinal) + 8);
                    break;
                }
            }

            return version;
        }

        /// <summary>
        /// Create a instance of the activity by reflection.
        /// </summary>
        /// <param name="activityType">The type of activity to be created.</param>
        /// <returns>The new activity instance.</returns>
        private static Activity CreateActivityInstance(Type activityType)
        {
            Activity wfAct = null;
            try
            {
                wfAct = Activator.CreateInstance(activityType) as Activity;
            }
            catch (System.Reflection.TargetInvocationException targetInvExp)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(
                  targetInvExp,
                  TridentErrorConstants.ErrorNumber6000013,
                  TridentResourceManager.GetString("ActivityInstanceCreateError", activityType.Name));
            }
            catch (Exception exp)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(
                   exp,
                   TridentErrorConstants.ErrorNumber6000013,
                   TridentResourceManager.GetString("ActivityInstanceCreateError", activityType.Name));
            }
            return wfAct;
        }

        /// <summary>
        /// Creates the AssemblyImage Package in the Registry for the activty actType.
        /// This package contains all the referenced DLL's of the activity actType.
        /// </summary>
        /// <param name="actType">Activty Type for which the AseemblyPackage has to be created.</param>
        /// <returns>AssemblyPackage instance.</returns>
        private void CreateAssemblyPackage(
            Er.Activity regActivity,
            Type actType,
            Collection<FileReference> references,
            bool containsActivity)
        {
            #region Validation of Arguments
            if (null == actType)
            {
                throw new ArgumentNullException("actType");
            }
            #endregion

            if (!actType.Assembly.GlobalAssemblyCache)
            {
                // Update the Assembly Image.
                // Do not Appened Datetime to the assembly package name. 
                // This is because we appened DateTime only when we are updating the Assembly Package
                Collection<Er.AssemblyPackage> asmPkgs = this.GetAssemblyPackage(references, containsActivity);
                foreach (Er.AssemblyPackage asmPkg in asmPkgs)
                {
                    if (!ActivityComposer.IsAssemblyPackageAvailable(regActivity.AssemblyPackages, asmPkg))
                    {
                        regActivity.AssemblyPackages.Add(asmPkg);
                    }
                }
            }
        }

        /// <summary>
        /// Creates the ComponentModel.Activity from the SimpleActivityModel.
        /// </summary>
        /// <param name="actModel">Activity Model for which the ComponentModel.Activty has to be created.</param>
        /// <param name="loadedAssemblyList">Assemblies which has been loaded.</param>
        /// <returns>ComponentModel.Activty created.</returns>
        private static Activity CreateCompModelActivity(
            SimpleActivityModel actModel,
            Collection<Assembly> loadedAssemblyList)
        {
            Activity wfAct = null;
            Type wfActType = null;

            // Search the type in all the assemblies which have been loaded.
            foreach (Assembly asm in loadedAssemblyList)
            {
                wfActType = asm.GetType(actModel.ActivityClass, false);
                if (null != wfActType)
                {
                    break;
                }
            }

            if (null != wfActType)
            {
                if (wfActType.IsSubclassOf(typeof(Activity)))
                {
                    wfAct = ActivityComposer.CreateActivityInstance(wfActType);

                    if (null != wfAct)
                    {
                        wfAct.Name = actModel.UniqueId;
                        wfAct.Description = actModel.Description;
                    }
                }
            }

            return wfAct;
        }

        /// <summary>
        /// Creates the ComponentModel.Activity from the SimpleActivityModel.
        /// </summary>
        /// <param name="actModel">Activity Model for which the ComponentModel.Activty has to be created.</param>
        /// <param name="referenceActivity">The activity to be used as reference when blackbox activity is being processed.</param>
        /// <param name="loadedAssemblyList">Assemblies which has been loaded.</param>
        /// <returns>ComponentModel.Activty created.</returns>
        private static Activity CreateCompModelActivity(
            SimpleBlackboxModel actModel,
            Activity referenceActivity,
            ServiceContainer serializerService)
        {
            #region Validation of Arguments
            if (null == actModel)
            {
                throw new ArgumentNullException("actModel");
            }
            if (null == referenceActivity)
            {
                throw new ArgumentNullException("referenceActivity");
            }
            #endregion

            // Search for the name of the blackbox activity in the reference activity.
            Activity reqActivity = referenceActivity.GetActivityByName(actModel.UniqueId);

            // Return a clone of the activity.
            return ActivityComposer.CreateClone(reqActivity, serializerService);
        }

        /// <summary>
        /// This function is used to retrieve the Assembly package related 
        /// to the the activity.
        /// If the Assembly package is not present then it is going to create 
        /// the Assembly package and then return newly created instance.
        /// </summary>
        /// <param name="packageName">Name of the assembly package.</param>
        /// <returns>Assembly package instance.</returns>
        private Er.AssemblyPackage GetAssemblyPackage(string packageName)
        {
            Er.AssemblyPackage asmPkg = null;

            try
            {
                if (Er.AssemblyPackage.Exists(packageName, this.registryConn))
                {
                    // Load the assembly package.
                    asmPkg = Er.AssemblyPackage.Load(packageName, this.registryConn);
                    RemoveUnusedAssemblies(asmPkg);
                }
                else
                {
                    // Create the assembly package.
                    asmPkg = Er.AssemblyPackage.Create(packageName, this.registryConn);
                }

                // Save the assembly package.
                asmPkg.Save();
            }
            catch (Exception exp)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(
                              exp, TridentErrorConstants.ErrorNumber6000017, exp.Message);
            }

            return asmPkg;
        }

        /// <summary>
        /// Delete unsed assemblies from the packages.
        /// </summary>
        /// <param name="asmPkg">Assembly Package.</param>
        private static void RemoveUnusedAssemblies(Er.AssemblyPackage asmPkg)
        {
            asmPkg.AssemblyImages.GetEnumerator();
            List<Er.AssemblyImage> images = asmPkg.AssemblyImages.ToList();

            // Clear relations.
            asmPkg.AssemblyImages.Clear();

            foreach (Er.AssemblyImage image in images)
            {
                image.Refresh();
                image.AssemblyPackages.GetEnumerator();
                if (image.AssemblyPackages.Count <= 0)
                {
                    image.DeleteUnused();
                }
            }
        }

        /// <summary>
        /// This function is used to create the Assembly imgae in registry.
        /// </summary>
        /// <param name="imageName">Assembly image name.</param>
        /// <param name="assemblyFile">Assembly File.</param>
        /// <returns>Assembly image instance.</returns>
        public Er.AssemblyImage CreateAssemblyImage(string imageName, FileInfo assemblyFile)
        {
            Er.AssemblyImage asmImg = null;
            if (null != assemblyFile)
            {
                try
                {
                    Er.AssemblyType type = Er.AssemblyType.Unknown;
                    if (Helper.IsAssemblyFile(assemblyFile.FullName))
                    {
                        if (Helper.IsManagedAssembly(assemblyFile.FullName))
                        {
                            type = Er.AssemblyType.DotNET;
                        }
                        else
                        {
                            type = Er.AssemblyType.WindowsDLL;
                        }
                    }
                    else
                    {
                        type = Er.AssemblyType.DataFile;
                    }

                    string newImageName;

                    // If an image already exists by the same name, add a timestamp to the image name.
                    Collection<Er.AssemblyImage> image = Er.AssemblyImage.CommonSearches.GetAssemblyImagesByName(imageName, this.registryConn);
                    if (image == null)
                    {
                        newImageName = imageName;
                    }
                    else
                    {
                        newImageName = string.Format(CultureInfo.InvariantCulture, "{0} - {1}", imageName, DateTime.Now.ToString(CultureInfo.CurrentCulture));
                    }

                    // Create the Assmbly Image.
                    asmImg = Er.AssemblyImage.Create(newImageName, type, this.registryConn);
                    asmImg.Save();

                    // Update the assembly Contents.
                    this.UpdateAssemblyImageContents(asmImg, assemblyFile);

                    asmImg.ContentsSize = (int)assemblyFile.Length;
                    asmImg.FileCreateDate = assemblyFile.CreationTime;
                    asmImg.FileModifyDate = assemblyFile.LastWriteTime;
                    asmImg.Filename = assemblyFile.Name;
                    asmImg.FileExtension = assemblyFile.Extension;

                    // Get the contents of the file to create a checksum. This byte array will also be used to create the image in registry.
                    byte[] fileContent = Helper.ReadBytesFromAssemblyFile(assemblyFile.FullName);
                    asmImg.Checksum = Helper.CreateChecksum(fileContent);

                    // Save the changes to registry.
                    asmImg.Save();
                }
                catch (Exception exp)
                {
                    TridentErrorHandler.HandleAndThrowBusinessLogicException(
                            exp,
                            TridentErrorConstants.ErrorNumber6000017,
                            exp.Message);
                }
            }

            return asmImg;
        }

        /// <summary>
        /// Updates the AssemblyImage Package in the Registry for the activty actType.
        /// Here we will not be updating the Assembly package but we would be creating
        /// one more assembly package of the Activity Type.
        /// </summary>
        /// <param name="actType">Activty Type for which the AseemblyPackage has to be updated.</param>
        /// <returns>AssemblyPackage instance.</returns>
        private Er.AssemblyPackage UpdateAssemblyPackage(Type actType, Collection<FileReference> references, bool containsActivity)
        {
            #region Validation of Arguments

            if (null == actType)
            {
                throw new ArgumentNullException("actType");
            }

            #endregion

            Collection<Er.AssemblyPackage> assemblyPackages = this.GetAssemblyPackage(references, containsActivity);
            if (assemblyPackages.Count > 0)
            {
                return assemblyPackages[0];
            }

            return null;
        }

        /// <summary>
        /// This function is used to update the Assembly image contents 
        /// in registry from the assembly file.
        /// </summary>
        /// <param name="asmImg">Assembly image which has to be updated.</param>
        /// <param name="assemblyFile">Assembly file.</param>
        /// <returns>AssemblyImage.</returns>
        private void UpdateAssemblyImageContents(Er.AssemblyImage asmImg, FileInfo assemblyFile)
        {
            // Workaround for saving the contents of the Assembly into Registry.
            // Remove thos once the autosave is implemented in Registry.
            this.registryConn.AutoSave = true;

            try
            {
                byte[] fileContent = Helper.ReadBytesFromAssemblyFile(assemblyFile.FullName);
                asmImg.Contents = fileContent;
                asmImg.Refresh();
            }
            finally
            {
                if (!this.installerInstance)
                {
                    this.registryConn.AutoSave = false;
                }
            }
        }


        /// <summary>
        /// Download the required dlls for the activity.
        /// </summary>
        /// <param name="rootActivity">The activity.</param>
        /// <param name="dllDirectoryPath">Path to be downloaded to.</param>
        private static void DownloadLibraries(Er.Activity rootActivity, string targetFolder)
        {
            // Sort based on name
            rootActivity.AssemblyPackages.GetEnumerator();
            rootActivity.AssemblyPackages.Sort((p1, p2) => DateTime.Compare(p2.Updated.When, p1.Updated.When));

            // foreach (AssemblyPackage package in rootActivity.AssemblyPackages)
            if (rootActivity.AssemblyPackages.Count > 0)
            {
                Er.AssemblyPackage package = rootActivity.AssemblyPackages[0];

                // Download the libraries form the activity.
                foreach (Er.AssemblyImage img in package.AssemblyImages)
                {
                    string targetFile = Path.Combine(targetFolder, img.Filename);

                    // if the file not exists in target folder and lib folder then download the file.
                    if (!File.Exists(targetFile) && img.Contents != null)
                    {
                        File.WriteAllBytes(targetFile, img.Contents);
                    }
                }
            }
        }

        /// <summary>
        /// Run through the model and its child models and update the respective activity info.
        /// </summary>
        /// <param name="model">
        /// Model.
        /// </param>
        /// <param name="rootActivity">
        /// The original root activity.
        /// </param>
        private void UpdateParameter(BaseModel model, Activity rootActivity, bool nullifyForCustomTypes)
        {
            if (model.IsSimpleActivityModel || model.IsCompositeActivityModel)
            {
                Activity activity = rootActivity.GetActivityByName(model.UniqueId);
                if (activity != null)
                {
                    foreach (ParameterDescriptionModel paramModel in model.InputParameters)
                    {
                        if (null == paramModel.Value && paramModel.IsMandatory)
                        {
                            continue;
                        }

                        try
                        {
                            PropertyInfo prop = activity.GetType().GetProperty(ActivityComposer.ShortName(paramModel.PropertyName));
                            DependencyProperty depProp =
                                   ActivityComposer.GetDependencyProperty(activity.GetType(), ActivityComposer.ShortName(paramModel.PropertyName) + "Property");

                            if (!paramModel.IsDatabound)
                            {
                                object parsedValue = null;
                                if (paramModel.Value != null)
                                {
                                    Er.TypeInitializer typeInit = TypeProviderHelper.FetchTypeInitializer(paramModel.DataType, Er.Runtime.WPF);
                                    if (null == typeInit)
                                    {
                                        parsedValue = TypeProviderHelper.FetchDeserializedValue(prop.PropertyType, paramModel.Value.ToString());

                                        if (parsedValue == null)
                                        {
                                            if (TypeDescriptor.GetConverter(prop.PropertyType).CanConvertFrom(typeof(string)))
                                            {
                                                parsedValue = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromString(paramModel.Value.ToString());
                                            }
                                        }
                                        //else
                                        //{
                                        //    if (nullifyForCustomTypes) parsedValue = null;
                                        //}
                                    }
                                    // else if (!nullifyForCustomTypes)
                                    else
                                    {
                                        string deserializedVal = (paramModel.Value == null) ? string.Empty : paramModel.Value.ToString();
                                        BaseTypeInitializer baseTypeInit = ActivityComposer.LoadInitializer(typeInit, deserializedVal);
                                        if (baseTypeInit != null)
                                        {
                                            parsedValue = baseTypeInit.GetValue();
                                        }
                                    }
                                }

                                activity.SetValue(depProp, parsedValue);
                            }
                            else
                            {
                                DatabindModel bindModel = paramModel.Value as DatabindModel;
                                if (null != bindModel)
                                {
                                    ActivityBind bind = new ActivityBind();
                                    bind.Name = bindModel.SourceActivityName;
                                    bind.Path = bindModel.SourcePropertyName;
                                    activity.SetBinding(depProp, bind);
                                }
                            }
                        }
                        catch (FileNotFoundException exp)
                        {
                            TridentErrorHandler.HandleAndThrowBusinessLogicException(
                                      exp,
                                      TridentErrorConstants.ErrorNumber6000013,
                                      TridentResourceManager.GetString("FileDependencyError"));
                        }
                        catch (Exception exp)
                        {
                            TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(exp);
                            TridentErrorHandler.HandleAndThrowBusinessLogicException(
                                exp,
                                TridentErrorConstants.ErrorNumber6000013,
                                exp.Message);
                        }
                    }
                }
            }

            if (model.IsCompositeActivityModel || model.IsSubsectionModel || model.IsCompositeBlackBoxModel)
            {
                BaseCompositeModel currentCompositeModel = model as BaseCompositeModel;
                foreach (BaseModel childModel in currentCompositeModel.Children)
                {
                    this.UpdateParameter(childModel, rootActivity, nullifyForCustomTypes);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private static Collection<string> ReadSupportedComponentModelActivities()
        {
            Collection<string> supportedActivities = new Collection<string>();

            try
            {
                // Read the xmldocument embedded in the dll.
                XmlDocument typeXml =
                     XmlUtilities.GetXmlResource(typeof(TridentUtilities.ActivityUtilities).Assembly,
                     "Microsoft.Research.ScientificWorkflow.TridentUtilities.Xml.SupportedActivities.xml");

                // Select all the activity nodes.
                XmlNodeList supportedActivityXmlList = typeXml.SelectNodes("//Activity");

                // Recurse through the nodelist and retreive the supported activities.
                foreach (XmlNode activityNode in supportedActivityXmlList)
                {
                    XmlAttribute nameAttribute = activityNode.Attributes["Name"];
                    if (nameAttribute != null && !string.IsNullOrEmpty(nameAttribute.Value))
                    {
                        supportedActivities.Add(nameAttribute.Value);
                    }
                }
            }
            catch
            {
                // Ignore any exception which occurs. Return an empty list.
            }
            return supportedActivities;
        }

        /// <summary>
        /// Create a clone of the activity needed for blackbox operations.
        /// </summary>
        /// <param name="activity">The activity to be cloned.</param>
        /// <returns>The cloned activity.</returns>
        private static Activity CreateClone(Activity activity, ServiceContainer serializationService)
        {
            string xomlString = string.Empty;
            Activity clone = null;
            List<Activity> tempStoreForChildren = new List<Activity>();

            WorkflowMarkupSerializationManager serializationManager = null;

            // Define the DesignerSerializationManager based on the ServiceContainer.
            DesignerSerializationManager manager = new DesignerSerializationManager(serializationService);

            CompositeActivity compositeActivity = activity as CompositeActivity;

            // Store the children before cloning.
            if (compositeActivity != null)
            {
                tempStoreForChildren.AddRange(compositeActivity.Activities);
                compositeActivity.Activities.Clear();
            }

            try
            {
                using (manager.CreateSession())
                {
                    serializationManager = new WorkflowMarkupSerializationManager(manager);

                    ActivityMarkupSerializer activitySerializer = new ActivityMarkupSerializer();

                    // Serialize the activity to xoml string.
                    using (StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture))
                    {
                        using (XmlWriter writer = XmlWriter.Create(stringWriter))
                        {

                            activitySerializer.Serialize(serializationManager, writer, activity);
                            xomlString = stringWriter.ToString();
                        }
                    }

                    // Deserialize the xoml to get a clone of the activity.
                    if (!string.IsNullOrEmpty(xomlString))
                    {
                        using (StringReader stringReader = new StringReader(xomlString))
                        {
                            using (XmlReader reader = XmlReader.Create(stringReader))
                            {
                                clone = (Activity)activitySerializer.Deserialize(serializationManager, reader) as Activity;
                            }
                        }
                    }

                    // Restore the children of the original activity.
                    if (compositeActivity != null)
                    {
                        compositeActivity.Activities.AddRange(tempStoreForChildren);
                    }
                }
            }
            catch (Exception ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                    TridentErrorConstants.ErrorNumber4000040,
                    TridentResourceManager.GetString("SaveWorkflowFailedToSavedIntoRegistry"));
            }

            return clone;
        }

        /// <summary>
        /// Iterates through the tree recursively to build a references table.
        /// For each activity in the list, builds all its references recursively.
        /// </summary>
        /// <param name="references">
        /// Collection of file references.
        /// </param>
        /// <returns>
        /// New collection of activity references.
        /// </returns>
        public static Collection<FileReference> BuildActivityReferences(Collection<FileReference> references)
        {
            Collection<FileReference> newList = new Collection<FileReference>();
            foreach (FileReference fileRef in references)
            {
                if (fileRef.ContainsActivity)
                {
                    Collection<string> allRefs = new Collection<string>();
                    foreach (string path in fileRef.References)
                    {
                        allRefs = ActivityComposer.BuildReferences(fileRef, path, allRefs, references);
                    }

                    newList.Add(FileReference.CreateCopy(fileRef));
                }
            }

            return newList;
        }

        /// <summary>
        /// Iterates through the tree recursively to build a references table.
        /// For each activity in the list, builds all its references recursively.
        /// </summary>
        /// <param name="references">
        /// Collection of file references.
        /// </param>
        /// <returns>
        /// New collection of activity references.
        /// </returns>
        public static Collection<FileReference> BuildTypeInitializerReferences(Collection<FileReference> references)
        {
            Collection<FileReference> newList = new Collection<FileReference>();
            foreach (FileReference fileRef in references)
            {
                if (ActivityComposer.IsTypeInitializer(fileRef.FilePath))
                {
                    Collection<string> allRefs = new Collection<string>();
                    foreach (string path in fileRef.References)
                    {
                        allRefs = ActivityComposer.BuildReferences(fileRef, path, allRefs, references);
                    }

                    FileReference newRef = new FileReference(fileRef.FilePath, allRefs);
                    newRef.ContainsActivity = false;
                    newList.Add(newRef);
                }
            }

            return newList;
        }

        /// <summary>
        /// Builds all references for an activity file recursively.
        /// </summary>
        /// <param name="activity">
        /// Activity FileReference.
        /// </param>
        /// <param name="refPath">
        /// Reference path.
        /// </param>
        /// <param name="allRefs">
        /// Collection of paths that is built by recursively iterating through the references.
        /// </param>
        /// <param name="references">
        /// The entire list of file references.
        /// </param>
        /// <returns>
        /// Collection of activity file references constructed.
        /// </returns>
        private static Collection<string> BuildReferences(
            FileReference activity,
            string refPath,
            Collection<string> allRefs,
            Collection<FileReference> references)
        {
            FileReference fileRef = references.FirstOrDefault(F => F.FilePath.Equals(refPath, StringComparison.OrdinalIgnoreCase));
            if (fileRef != null)
            {
                if (!refPath.Equals(activity.FilePath, StringComparison.OrdinalIgnoreCase))
                {
                    allRefs.Add(refPath);
                    foreach (string strPath in fileRef.References)
                    {
                        if (refPath.Equals(strPath, StringComparison.OrdinalIgnoreCase) || allRefs.Contains(strPath))
                        {
                            continue;
                        }
                        else
                        {
                            ActivityComposer.BuildReferences(activity, strPath, allRefs, references);
                        }
                    }
                }
            }

            return allRefs;
        }

        #endregion

        #region Contains function

        /// <summary>
        /// Check whether assembly image object is exists in collection of assembly package or not.
        /// </summary>
        /// <param name="assemblyImages">AssemblyImage Collection.</param>
        /// <param name="assemblyImageSR">AssemblyImage which has to be searched for.</param>
        /// <returns>Whether AssemblyImage is available in the collection or not.</returns>
        public static bool IsAssemblyImageAvailable(Er.AssemblyImageCollection<Er.AssemblyPackage> assemblyImages, Er.NamedObject<Er.AssemblyImage> assemblyImageSR)
        {
            bool isFound = false;

            foreach (Er.AssemblyImage assemblyImage in assemblyImages)
            {
                if (String.Equals(assemblyImage.Name, assemblyImageSR.Name, StringComparison.OrdinalIgnoreCase))
                {
                    isFound = true;
                    break;
                }
            }

            return isFound;
        }

        /// <summary>
        /// Check whether assembly package object is exists in collection of assembly package or not.
        /// </summary>
        /// <param name="assemblyPkgs">AssemblyPackage Collection.</param>
        /// <param name="checkAssemblyPkg">AssemblyPackage which has to be searched for.</param>
        /// <returns>Whether AssemblyPackage is available in the collection or not.</returns>
        public static bool IsAssemblyPackageAvailable(Er.AssemblyPackageCollection<Er.Activity> assemblyPackages, Er.NamedObject<Er.AssemblyPackage> checkAssemblyPackage)
        {
            bool isFound = false;

            foreach (Er.AssemblyPackage assemblyPkg in assemblyPackages)
            {
                if (String.Equals(assemblyPkg.Name, checkAssemblyPackage.Name, StringComparison.OrdinalIgnoreCase))
                {
                    isFound = true;
                    break;
                }
            }

            return isFound;
        }

        /// <summary>
        /// Check whether assembly package object is exists in collection.
        /// </summary>
        /// <param name="assemblyPkgs">AssemblyPackage Collection.</param>
        /// <param name="checkAssemblyPkg">AssemblyPackage which has to be searched for.</param>
        /// <returns>Whether AssemblyPackage is available in the collection or not.</returns>
        public static bool IsAssemblyPackageAvailable(Collection<Er.AssemblyPackage> assemblyPackages, Er.NamedObject<Er.AssemblyPackage> checkAssemblyPackage)
        {
            bool isFound = false;

            foreach (Er.AssemblyPackage assemblyPkg in assemblyPackages)
            {
                if (String.Equals(assemblyPkg.Name, checkAssemblyPackage.Name, StringComparison.OrdinalIgnoreCase))
                {
                    isFound = true;
                    break;
                }
            }

            return isFound;
        }

        #endregion

        #region TypeInitializer Code

        /// <summary>
        /// Gets a value indicating if the file contains a type initializer or not.
        /// </summary>
        /// <param name="filePath">
        /// Path of the file.
        /// </param>
        /// <returns>
        /// True if the file contains a type initializer, False otherwise.
        /// </returns>
        public static bool IsTypeInitializer(string filePath)
        {
            bool isTypeInitializer = false;
            if (Helper.IsManagedAssembly(filePath))
            {
                Assembly assembly = AssemblyLoad.LoadFrom(filePath);
                foreach (System.Type customTypeInitializer in assembly.GetTypes())
                {
                    // Search only the BaseTypeInitializer types.
                    if (customTypeInitializer.IsSubclassOf(typeof(BaseTypeInitializer)))
                    {
                        isTypeInitializer = true;
                        break;
                    }
                }
            }

            return isTypeInitializer;
        }

        /// <summary>
        /// Create the custom type initializer.
        /// </summary>
        /// <param name="customTypeInitializer">
        /// The custom type.
        /// </param>
        /// <returns>
        /// The registry object.
        /// </returns>
        private Er.TypeInitializer CreateCustomTypeInitializer(Type customTypeInitializer)
        {
            Er.TypeInitializer typeInitializer = null;
            Er.Runtime runtimeSupported = Er.Runtime.WPF;
            Er.TridentTypeInfo tridentTypeInfo = null;
            try
            {
                // Create an instance, read its values to create the registry object.
                BaseTypeInitializer baseTypeInit = Activator.CreateInstance(customTypeInitializer) as BaseTypeInitializer;
                if (baseTypeInit != null)
                {
                    runtimeSupported = baseTypeInit.SupportedRuntime;
                    tridentTypeInfo = this.FetchTridentTypeInfo(baseTypeInit);
                    if (tridentTypeInfo != null)
                    {
                        typeInitializer = Er.TypeInitializer.Create(customTypeInitializer.FullName, runtimeSupported, tridentTypeInfo, this.registryConn);
                        typeInitializer.AssemblyName = customTypeInitializer.Assembly.CodeBase;
                        typeInitializer.QualifiedName = customTypeInitializer.Assembly.FullName;
                        typeInitializer.ClassName = customTypeInitializer.FullName;
                        typeInitializer.Save();
                    }
                }
            }
            catch (ArgumentException ex)
            {
                TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000042, ex.Message);
            }
            catch (NotSupportedException ex)
            {
                TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000043, ex.Message);
            }
            catch (TargetInvocationException ex)
            {
                TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000044, ex.Message);
            }
            catch (MethodAccessException ex)
            {
                TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000045, ex.Message);
            }
            catch (MemberAccessException ex)
            {
                TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000046, ex.Message);
            }
            catch (TypeLoadException ex)
            {
                TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000047, ex.Message);
            }

            return typeInitializer;
        }

        /// <summary>
        /// Update the existing registry object.
        /// </summary>
        /// <param name="typeInitializer">
        /// The registry object to be updated.
        /// </param>
        /// <param name="customTypeInitializer">
        /// The custom type.
        /// </param>
        private void UpdateCustomTypeInitializer(Er.TypeInitializer typeInitializer, Type customTypeInitializer)
        {
            if (typeInitializer == null)
            {
                throw new ArgumentNullException("typeInitializer");
            }

            if (customTypeInitializer == null)
            {
                throw new ArgumentNullException("customTypeInitializer");
            }

            try
            {
                // Create the instance and update the registry object with info from it.
                Er.TridentTypeInfo tridentTypeInfo = null;
                BaseTypeInitializer baseTypeInit = Activator.CreateInstance(customTypeInitializer) as BaseTypeInitializer;
                if (baseTypeInit != null)
                {
                    tridentTypeInfo = this.FetchTridentTypeInfo(baseTypeInit);
                    if (tridentTypeInfo != null)
                    {
                        typeInitializer.AssemblyName = customTypeInitializer.Assembly.CodeBase;
                        typeInitializer.QualifiedName = customTypeInitializer.Assembly.FullName;
                        typeInitializer.ClassName = customTypeInitializer.FullName;
                        typeInitializer.RelatedType = tridentTypeInfo;
                        typeInitializer.Save();
                    }
                }
            }
            catch (ArgumentException ex)
            {
                TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000048, ex.Message);
            }
            catch (NotSupportedException ex)
            {
                TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000049, ex.Message);
            }
            catch (TargetInvocationException ex)
            {
                TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000050, ex.Message);
            }
            catch (MethodAccessException ex)
            {
                TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000050, ex.Message);
            }
            catch (MemberAccessException ex)
            {
                TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000051, ex.Message);
            }
            catch (TypeLoadException ex)
            {
                TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000052, ex.Message);
            }
        }

        /// <summary>
        /// Fetch the TridentTypeInfo for the passed initializer.
        /// </summary>
        /// <param name="baseTypeInit">
        /// The tridentTypeInitializer.
        /// </param>
        /// <returns>
        /// The related trident type info.
        /// </returns>
        private Er.TridentTypeInfo FetchTridentTypeInfo(BaseTypeInitializer baseTypeInit)
        {
            Er.TridentTypeInfo tridentTypeInfo = null;
            if (baseTypeInit != null)
            {
                tridentTypeInfo = Er.TridentTypeInfo.CommonSearches.FetchTridentTypeInfo(baseTypeInit.CustomType.FullName, this.registryConn);
                if (null == tridentTypeInfo)
                {
                    tridentTypeInfo = this.CreateTridentTypeInfo(baseTypeInit.CustomType);
                }
                else
                {
                    ActivityComposer.UpdateTridentTypeInfo(tridentTypeInfo);
                }
            }

            return tridentTypeInfo;
        }

        /// <summary>
        /// Create a new TridentTypeInfo entry in the registry.
        /// </summary>
        /// <param name="customTypeInfo">
        /// The custom type for which an entry is to be made.
        /// </param>
        /// <param name="color">
        /// The color to be supported.
        /// </param>
        /// <returns>
        /// The type info.
        /// </returns>
        private Er.TridentTypeInfo CreateTridentTypeInfo(Type customTypeInfo)
        {
            Er.TridentTypeInfo tridentTypeInfo = null;
            if (customTypeInfo != null)
            {
                tridentTypeInfo = Er.TridentTypeInfo.Create(customTypeInfo.FullName, this.registryConn);
                tridentTypeInfo.TypeName = customTypeInfo.FullName;
                tridentTypeInfo.Save();
            }

            return tridentTypeInfo;
        }

        /// <summary>
        /// Update an existing type info.
        /// </summary>
        /// <param name="tridentTypeInfo">
        /// Existing type info.
        /// </param>
        /// <param name="color">
        /// Color to be supported.
        /// </param>
        private static void UpdateTridentTypeInfo(Er.TridentTypeInfo tridentTypeInfo)
        {
            tridentTypeInfo.Save();
        }

        /// <summary>
        /// Get a list of custom type initializers in the assembly already existing in the registry.
        /// </summary>
        /// <param name="custom types assembly"></param>
        /// <returns></returns>
        private List<Er.TypeInitializer> GetExistingCustomTypeInitializersList(Assembly typesAssembly)
        {
            List<Er.TypeInitializer> typeInitializersList = new List<Er.TypeInitializer>();

            // Iterate through all the assemblies.
            foreach (System.Type customType in typesAssembly.GetTypes())
            {
                // Search only the activity types.
                if (customType.IsSubclassOf(typeof(BaseTypeInitializer)))
                {
                    Er.TypeInitializer registryType = this.FindCustomTypesInRegistry(customType);
                    if (registryType != null)
                    {
                        typeInitializersList.Add(registryType);
                    }
                }
            }

            return typeInitializersList;
        }

        /// <summary>
        /// Check if custom type initializer is already present in registry.
        /// </summary>
        /// <param name="type">the type of the custom type initializer to find.</param>
        /// <returns>Returns the custom type initializer found in the registry.</returns>
        private Er.TypeInitializer FindCustomTypesInRegistry(System.Type type)
        {
            #region Validation of Arguments

            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            #endregion

            string typeClass = string.Format(CultureInfo.CurrentUICulture, "{0}.{1}", type.Namespace, type.Name);
            return Er.TypeInitializer.CommonSearches.FindCustomTypesInRegistry(typeClass, this.registryConn);
        }

        /// <summary>
        /// Check whether customTypeInitializer object is exists in collection of customTypeInitializers or not.
        /// </summary>
        /// <param name="activities">customTypeInitializers collection.</param>
        /// <param name="activitySR">customTypeInitializer which has to be searched for.</param>
        /// <returns>Whether customTypeInitializer is available in the collection or not.</returns>
        private static Er.TypeInitializer FetchCustomTypeInitializerIfAvailable(
            List<Er.TypeInitializer> typeInitializers,
            string typeName)
        {
            Er.TypeInitializer foundType = null;
            foreach (Er.TypeInitializer customTypeInitializer in typeInitializers)
            {
                if (String.Equals(customTypeInitializer.Name, typeName, StringComparison.OrdinalIgnoreCase))
                {
                    foundType = customTypeInitializer;
                    break;
                }
            }

            return foundType;
        }

        /// <summary>
        /// Check whether assembly package object is exists in collection of assembly package or not.
        /// </summary>
        /// <param name="assemblyPkgs">AssemblyPackage Collection.</param>
        /// <param name="checkAssemblyPkg">AssemblyPackage which has to be searched for.</param>
        /// <returns>Whether AssemblyPackage is available in the collection or not.</returns>
        private static bool FetchAssemblyPackageIfAvailableCustomType(
            Er.AssemblyPackageCollection<Er.TypeInitializer> assemblyPackages,
            Er.NamedObject<Er.AssemblyPackage> checkAssemblyPackage)
        {
            bool isFound = false;
            foreach (Er.AssemblyPackage assemblyPkg in assemblyPackages)
            {
                if (String.Equals(assemblyPkg.Name, checkAssemblyPackage.Name, StringComparison.OrdinalIgnoreCase))
                {
                    isFound = true;
                    break;
                }
            }

            return isFound;
        }

        /// <summary>
        /// This method loads the type initalizer assembly and then 
        /// creates an instance of the initializer control.
        /// </summary>
        /// <returns>The base type initializer</returns>
        public static BaseTypeInitializer LoadInitializer(Er.TypeInitializer typeInit, string deserializedValue)
        {
            return TypeProviderHelper.LoadInitializer(typeInit, deserializedValue);
        }

        /// <summary>
        /// Download the custom type initializer libraries for all the input parameters in the given model.
        /// </summary>
        /// <param name="model">
        /// Model to download libraries for.
        /// </param>
        /// <param name="targetFolder">
        /// The target location.
        /// </param>
        private static void DownloadCustomInitializerLibraries(BaseModel model, string targetFolder)
        {
            foreach (ParameterDescriptionModel paramModel in model.InputParameters)
            {
                Er.TypeInitializer typeInit = TypeProviderHelper.FetchTypeInitializer(paramModel.DataType, Er.Runtime.WPF);
                if (null != typeInit)
                {
                    ActivityComposer.DownloadCustomInitializerLibraries(typeInit, targetFolder);
                }
            }
        }

        /// <summary>
        /// Download the custom type initializer libraries for the passed activity sequences.
        /// </summary>
        /// <param name="activitySeq">
        /// ActivitySequence for which to get the custom type initializers.
        /// </param>
        /// <param name="targetFolder">
        /// The target folder.
        /// </param>
        public static void DownloadCustomInitializerLibraries(Er.ActivitySequence activitySeq, string targetFolder)
        {
            foreach (Er.ParameterAssignment paramAssign in activitySeq.ParameterAssignments)
            {
                if (paramAssign.ActivityParameter.Direction == Er.DirectionType.Input)
                {
                    Er.TypeInitializer typeInit = TypeProviderHelper.FetchTypeInitializer(paramAssign.ActivityParameter.Type, Er.Runtime.WPF);
                    if (null != typeInit)
                    {
                        ActivityComposer.DownloadCustomInitializerLibraries(typeInit, targetFolder);
                    }
                }
            }
        }

        /// <summary>
        /// Download the required dlls for the custom type initializer.
        /// </summary>
        /// <param name="rootActivity">The custom type initializer.</param>
        /// <param name="dllDirectoryPath">Path to be downloaded to.</param>
        public static void DownloadCustomInitializerLibraries(Er.TypeInitializer typeInitializer, string targetFolder)
        {
            TypeProviderHelper.DownloadCustomInitializerLibraries(typeInitializer, targetFolder);
        }

        #endregion TypeInitializer Code
    }
}
